﻿/*
 *  date: 2018-04-21
 *  author: John-chen
 *  cn: 事件控制器基类
 *  en: todo:
 */

using System.Linq;
using System.Collections.Generic;

namespace JyFramework
{
    /// <summary>
    /// 事件控制器基类
    /// </summary>
    public class EventController : IEvent
    {
        public string Name { get { return _name; } }

        public HandlerMsg OnRegistMsgEvent;
        public HandlerMsg OnRemoveMsgEvent;
        public MessageNotify OnNotifyEvent;

        public Dictionary<string, List<MessageHandler>> Events { get { return _events; } }

        public EventController(string name = "EventController")
        {
            _name = name + "EventCtrl";
            _events = new Dictionary<string, List<MessageHandler>>();
        }

        /// <summary>
        /// 添加控制器时初始化函数
        /// </summary>
        public virtual void OnInit()
        {
        }

        /// <summary>
        /// 移除控制器时执行的函数
        /// </summary>
        public virtual void OnRemove()
        {
            RemoveAllEvents();
        }

        /// <summary>
        /// 注册事件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="eventAction"></param>
        public void RegistEvent(string name, MessageHandler eventAction)
        {
            List<MessageHandler> actions = null;
            if (_events.TryGetValue(name, out actions))
            {
                actions.Add(eventAction);
            }
            else
            {
                actions = new List<MessageHandler>();
                actions.Add(eventAction);
                _events.Add(name, actions);
            }

            OnRegistMsgEvent?.Invoke(name, eventAction);
        }

        /// <summary>
        /// 通知事件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="args"></param>
        public void NotifyEvent(string name, params object[] args)
        {
            if (OnNotifyEvent == null)
            {
                List<MessageHandler> actions = null;
                if (_events.TryGetValue(name, out actions))
                {
                    foreach (var e in actions)
                    {
                        e(args);
                    }
                }
                else
                {
                    // log the event name = name is null
                }
            }
            else
            {
                OnNotifyEvent?.Invoke(name, args);
            }
        }

        /// <summary>
        /// 移除事件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="eventAction"></param>
        public void RemoveEvent(string name, MessageHandler eventAction)
        {
            List<MessageHandler> actions = null;
            if (_events.TryGetValue(name, out actions))
            {
                actions.Remove(eventAction);
                if (actions.Count <= 0)
                {
                    _events[name].Clear();
                    _events.Remove(name);
                }
            }

            OnRemoveMsgEvent?.Invoke(name, eventAction);
        }

        /// <summary>
        /// 移除事件列表
        /// </summary>
        /// <param name="name"></param>
        /// <param name="eventList"></param>
        protected void RemoveEventList(string name, List<MessageHandler> eventList)
        {
            if(eventList == null || eventList.Count == 0) return;

            int cnt = eventList.Count - 1;

            for (int i = cnt; i >= 0; i--)
            {
                RemoveEvent(name, eventList[i]);
            }
        }

        /// <summary>
        /// 移除所有的事件
        /// </summary>
        protected void RemoveAllEvents()
        {
            if(_events == null || _events.Count == 0) return;

            var keyList = _events.Keys.ToArray();
            int cnt = keyList.Length - 1;
            for (int i = cnt; i >= 0; i--)
            {
                var key = keyList[i];
                RemoveEventList(key, _events[key]);
            }

            _events.Clear();
        }

        protected string _name;
        protected Dictionary<string, List<MessageHandler>> _events;
    }
}
